import Particle from './Particle.js'

let mAngleX = 0,
	mAngleY = 0,
	mAngleZ = 0,
	maxDelta = -Infinity,
	minDelta = Infinity,
	sinAngleX, cosAngleX, sinAngleY, cosAngleY, sinAngleZ, cosAngleZ;

function sineCosine(mAngleX, mAngleY, mAngleZ) {
	const degToRad = (Math.PI / 180);
	sinAngleX = Math.sin(mAngleX * degToRad);
	cosAngleX = Math.cos(mAngleX * degToRad);
	sinAngleY = Math.sin(mAngleY * degToRad);
	cosAngleY = Math.cos(mAngleY * degToRad);
	sinAngleZ = Math.sin(mAngleZ * degToRad);
	cosAngleZ = Math.cos(mAngleZ * degToRad);
}

export default class PlanetCalculator {

	constructor(canvasInfo) {
		/** @type {{ctx:Uni.CanvasContext,width:number,height:number}} */
		this.canvasInfo = canvasInfo;

		this.radius = Math.min(this.canvasInfo.width, this.canvasInfo.height) * 0.5 * 0.8
		this.particles = []

		maxDelta = minDelta = 2 * this.radius

		// this.drawBg();
		// const {ctx} = this.canvasInfo
		
		// ctx.beginPath()
		// ctx.rect(10,10,300,300)
		// ctx.setFillStyle('green')
		// ctx.fill()
		
		// ctx.save()
		
		// ctx.beginPath();
		// ctx.rect(90,90,110,110)
		// ctx.clip();
		
		// ctx.beginPath();
		// ctx.arc(100, 100, 30, 0, 2 * Math.PI)
		// ctx.setFillStyle('red')
		// ctx.fill()
		
		// ctx.beginPath()
		
		// ctx.setFillStyle('block')
		// ctx.fillText('这是测试文字', 90,90)
		
		// ctx.setStrokeStyle('block')
		// ctx.strokeText('这是测试文字', 90,90);
		
		// ctx.restore();
		
		// this.canvasInfo.ctx.draw()
	}
	setSize(x,y){
		if(this.canvasInfo){
			this.canvasInfo.width = x;
			this.canvasInfo.height = y;
		}
	}

	

	setData(data = []) {
		const {
			radius
		} = this;
		const count = data.length
		this.particles = data.map((da, index) => {
			const particle = new Particle(this.canvasInfo)
			particle.data = da;

			const i = index + 1
			const phi = Math.acos(-1 + (2.0 * i - 1.0) / count);
			const theta = Math.sqrt(count * Math.PI) * phi;

			particle.x = radius * Math.cos(theta) * Math.sin(phi)
			particle.y = radius * Math.sin(theta) * Math.sin(phi)
			particle.z = radius * Math.cos(phi)

			return particle
		})

		sineCosine(mAngleX, mAngleY, mAngleZ);
		this.updateAllModal();
		this.draw();
		this.startAnimation();
	}

	updateAllModal() {
		this.particles.forEach(p => {
			// 此部分有两个选项：
			// 绕x轴旋转
			const rx1 = p.x;
			const ry1 = p.y * cosAngleX + p.z * -sinAngleX;
			const rz1 = p.y * sinAngleX + p.z * cosAngleX;
			// 绕y轴旋转
			const rx2 = rx1 * cosAngleY + rz1 * sinAngleY;
			const ry2 = ry1;
			const rz2 = rx1 * -sinAngleY + rz1 * cosAngleY;
			// 绕z轴旋转
			const rx3 = rx2 * cosAngleZ + ry2 * -sinAngleZ;
			const ry3 = rx2 * sinAngleZ + ry2 * cosAngleZ;
			const rz3 = rz2;

			p.x = rx3
			p.y = ry3
			p.z = rz3

			// 添加透视图
			const diameter = 2 * this.radius;
			const per = diameter / (diameter + rz3);
			// 让我们为标签设置位置、比例和透明度
			p.scale = per

			// 计算透明度
			const delta = diameter + rz3;
			maxDelta = Math.max(maxDelta, delta);
			minDelta = Math.min(minDelta, delta);
			const alpha = (delta - minDelta) / (maxDelta - minDelta);
			p.alpha = 1 - alpha;
		})

		this.particles.sort((a, b) => {
			return b.scale - a.scale
		})
	}

	setAngleMove(dx,dy){
		mAngleX = dy / this.radius * 180
		mAngleY = -dx / this.radius * 180
	}
	setMAngleX(angle) {
		mAngleX = angle
	}
	setMAngleY(angle) {
		mAngleY = angle
	}
	stopAnimation() {
		clearInterval(this.__timer);
	}
	startAnimation() {
		this.stopAnimation()
		this.__timer = setInterval(() => {
			this.setMAngleX(0);
			this.setMAngleY(0.5)
			this.update()
		}, 100)
	}

	// 更新
	update() {
		if (Math.abs(mAngleX) > .1 || Math.abs(mAngleY) > .1) {
			sineCosine(mAngleX, mAngleY, mAngleZ);
			this.updateAllModal()
			this.draw();
		}
	}
	
	drawBg() {
		// const {
		// 	ctx,
		// 	width,
		// 	height
		// } = this.canvasInfo
		// ctx.clearRect(0, 0, width, height)
		// ctx.beginPath();
		// ctx.rect(0, 0, width, height)
		// ctx.setFillStyle('#131313')
		// ctx.fill()
		// ctx.closePath()
	}

	// 画
	draw() {
		if(!this.canvasInfo?.ctx)return;
		const {ctx} = this.canvasInfo
		ctx.restore();
		ctx.save();
		// this.drawBg();
		this.particles.forEach(p => p.draw())
		this.canvasInfo.ctx.draw()
	}
}